package com.deep.deepenterpise.common.lock;


import com.deep.deepenterpise.common.code.DrCodeMsg;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

@Service
@Slf4j
public class DrLockService {
    @Resource
    private RedissonClient redissonClient;

    public <T> T executeWithLockThrows(String key, int waitTime, TimeUnit unit, SupplierThrow<T> supplier)
            throws Throwable {
        RLock lock = redissonClient.getLock(key);
        try {
            boolean lockSuccess = lock.tryLock(waitTime, unit);
            if (!lockSuccess) {
                throw new IllegalArgumentException(DrCodeMsg.SYSTEM_BUSY_ERR.getMsg());
            }
            // 执行锁内的代码逻辑
            return supplier.get();
        } finally {
            lock.unlock();
        }
    }

    @SneakyThrows
    public <T> T executeWithLock(String key, int waitTime, TimeUnit unit, Supplier<T> supplier) {
        return executeWithLockThrows(key, waitTime, unit, supplier::get);
    }

    @FunctionalInterface
    public interface SupplierThrow<T> {

        /**
         * Gets a result.
         *
         * @return a result
         */
        T get() throws Throwable;
    }

    /**
     * 获取锁
     *
     * @param key key
     * @return org.redisson.api.RLock
     * @author xxx
     * @date 2020/10/13 5:21 下午
     */
    public RLock getRLock(String key) {
        return redissonClient.getLock(key);
    }
}